/*
 * Clocks.c Version 1.0
 *
 *  Created on: Oct 20, 2013
 *      Author: PabloFR
 */

#include "Clocks.h"


	/* Function configures external oscillator in order to introduce it as reference to a PLL clock,
	 * Allowed frequencies are "high" and "very high"
	 * 
	 * IMPORTANT NOTE: Paramameters should be direct values at Frdiv,Prdiv,Vdiv 
	 * (example: dividing FLL by 32 uses F32, dividing PLL by 3 use "3")
	 * 
	 * More info: Page 409 Reference manual Kinetis KL46z
	 */

void FEI_to_PEE_Clock_Config(uint8_t Freq, uint8_t Gain, uint8_t Frdiv,uint8_t Prdiv,uint8_t Vdiv,
		uint8_t Clkdiv1, uint8_t Clkdiv2) {
	
	//FEI to FBE mode : 
		/* Enables the External Reference Clock Request*/ 
		OSC0_CR = OSC_CR_ERCLKEN_MASK; 
		/* Configure Frequency, Gain and select Oscillator   */
		MCG_C2 = MCG_C2_RANGE0(Freq & 2)| ((Gain & 1) << MCG_C2_HGO0_SHIFT) | MCG_C2_EREFS0_MASK;
		/* External clock as reference clk and select division*/
		MCG_C1 = (2<<MCG_C1_CLKS_SHIFT) | ((Frdiv & 3)<<MCG_C1_FRDIV_SHIFT); //NOTE :31.25 kHz to 39.0625 kHz range required by the FLL
		/* Wait until OSCINIT0 bit is set indicating that external clock is initialized */ 
		while (!(MCG_S & (MCG_S_OSCINIT0_MASK))); 
		/* Wait until Internal Reference Select bit is 0 */ 
		while (MCG_S & (MCG_S_IREFST_MASK));
		/* Wait until external reference clock is the one used as system clock */ 
		while ((MCG_S & MCG_S_CLKST_MASK) != 0x08); 
	/* Set PRDIV to divide  */ 
	MCG_C5 = MCG_C5_PRDIV0(Prdiv-1); 
	//FBE to PBE mode :
		/* Turn On PLLS to enable PLL, Multiply PLL time 24, output clock is 96 MHz */ 
		MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV0((Vdiv-24) & 0x1F); 
	/* Loop until MCG_S has set PLLST and LOCK0 */ 
	while (!(MCG_S & (MCG_S_LOCK0_MASK | MCG_S_PLLST_MASK))); 
	/* Divide for  system clock and  bus clock */ 
	SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1((Clkdiv1&0x1F)-1) | SIM_CLKDIV1_OUTDIV4((Clkdiv2&0x1F)-1); 
	/* Select PLL as the system clock */ 
	MCG_C1 = 0x18; 
	/* Wait until PLL is the one used as system clock */ 
	while ((MCG_S & MCG_S_CLKST_MASK) != 0x0C); 
}
